package com.gobrs.async.core;

import com.gobrs.async.core.common.domain.AsyncParam;
import com.gobrs.async.core.common.domain.AsyncResult;
import com.gobrs.async.core.common.exception.NotTaskRuleException;
import com.gobrs.async.core.task.AsyncTask;

import java.util.*;

/**
 * 给每条规则配置创建一个任务流，并给每一个任务流创建一个任务触发器
 * 负责任务流执行的触发(go方法)
 */
public class GobrsAsync {

    /**
     * 一条规则对应一个任务流：ruleName -> TaskFlow
     */
    private Map<String, TaskFlow> taskFlow;

    /**
     * 一条规则对应一个触发器：ruleName -> TaskTrigger
     */
    private Map<String, TaskTrigger> trigger;

    /**
     * 根据任务名称开始任务接收
     */
    public TaskReceive begin(String taskName, AsyncTask... tasks) {
        return taskFlow.get(taskName).start(tasks);
    }

    /**
     * 开始构建任务流程
     */
    public TaskReceive begin(String ruleName, List<AsyncTask> asyncTasks, boolean reload) {
        if (Objects.isNull(taskFlow)) {
            loadTaskFlow(ruleName);
        }
        if (Objects.isNull(taskFlow.get(ruleName))) {
            loadTaskFlowFirst(ruleName);
        }
        if (reload) {
            loadTaskFlowFirst(ruleName);
        }
        return taskFlow.get(ruleName).start(asyncTasks);
    }

    /**
     * 根据规则名称开始接收任务
     */
    public TaskReceive begin(String ruleName, List<AsyncTask> asyncTasks) {
        return begin(ruleName, asyncTasks, false);
    }

    /**
     * 添加子任务流程
     */
    public TaskReceive after(String taskName, AsyncTask... tasks) {
        return taskFlow.get(taskName).after(tasks);
    }

    /**
     * 根据规则名称启动任务流程
     */
    public AsyncResult go(String ruleName, AsyncParam param, long timeout) {
        return go(ruleName, param, null, timeout);
    }

    /**
     * 根据规则名称启动任务流程
     */
    public AsyncResult go(String ruleName, AsyncParam param, Set<String> optionalTasks, long timeout) {
        if (check(ruleName).isPresent()) {
            return trigger.get(ruleName).trigger(param, timeout, optionalTasks).load();
        }
        throw new NotTaskRuleException("Gobrs Rule Name Is Error!!!");
    }

    /**
     * 根据任务名称启动任务流程
     */
    public AsyncResult go(String taskName, AsyncParam param) {
        return go(taskName, param, 0L);
    }

    /**
     * 预加载任务触发器
     */
    public synchronized void readyTo(String ruleName) {
        readyTo(ruleName, false);
    }

    /**
     * 预加载任务触发器
     */
    public synchronized void readyTo(String ruleName, boolean reload) {
        /**
         * 初始化任务触发器
         */
        if (Objects.isNull(trigger)) {
            initialize(ruleName);
        }
        /**
         * 加载任务触发器
         */
        if (Objects.isNull(trigger.get(ruleName))) {
            load(ruleName);
        }
        if (reload) {
            load(ruleName);
        }
    }

    /**
     * 加载任务流
     */
    private void loadTaskFlow(String ruleName) {
        taskFlow = new HashMap<>();
        TaskFlow tf = new TaskFlow();
        taskFlow.put(ruleName, tf);
    }

    /**
     * 加载第一个任务处理程序
     */
    private void loadTaskFlowFirst(String ruleName) {
        TaskFlow tf = new TaskFlow();
        taskFlow.put(ruleName, tf);
    }

    /**
     * 初始化任务触发器
     */
    private void initialize(String ruleName) {
        trigger = new HashMap<>();
        TaskTrigger tr = new TaskTrigger(ruleName, taskFlow.get(ruleName));
        trigger.put(ruleName, tr);
    }

    /**
     * 创建第一个任务触发器
     */
    private void load(String ruleName) {
        TaskTrigger tr = new TaskTrigger(ruleName, taskFlow.get(ruleName));
        trigger.put(ruleName, tr);
    }

    /**
     * 检查任务流规则
     */
    private Optional<TaskTrigger> check(String ruleName) {
        return Optional.ofNullable(trigger.get(ruleName));
    }

}
